package service

import (
	"code.huawei.com/tdc-sdk/client"
	"code.huawei.com/tdc-sdk/utils"
	"encoding/json"
	"github.com/pkg/errors"
	"nft-server/config"
	"nft-server/logger"
	"nft-server/util"
	"strconv"
)

type BlockSummary struct {
	Blocks int `json:"blocks"`
	Txs    int `json:"txs"`
}

type Transaction struct {
	BlockID string `json:"block_id"`
	TxId    string `json:"tx_id"`
	Time    string `json:"time"`
}

type BlockList struct {
	Count  int     `json:"count"`
	Blocks []Block `json:"blocks"`
}

type Block struct {
	Id       int                      `json:"id"`
	TxsCount int                      `json:"txs_count"`
	DataHash string                   `json:"data_hash"`
	PreHash  string                   `json:"pre_hash"`
	Time     string                   `json:"time"`
	Txs      []GetTransactionResponse `json:"txs"`
}

type GetTransactionResponse struct {
	TxId          string     `json:"tx_id"`
	Type          string     `json:"type"`
	BlockID       int        `json:"block_id"`
	Creator       string     `json:"creator"`
	CreateTime    string     `json:"create_time"`
	ChaincodeName string     `json:"chaincode_name"`
	EndorsorOrgs  []string   `json:"endorsor_orgs"`
	ReadSet       []ReadSet  `json:"read_set"`
	WriteSet      []WriteSet `json:"write_set"`
}

type ReadSet struct {
	Key     string  `json:"key"`
	Version Version `json:"version"`
}
type Version struct {
	BlockNum int `json:"block_num"`
	TxNum    int `json:"tx_num"`
}

type WriteSet struct {
	Key       string `json:"key"`
	Value     string `json:"value"`
	Signature string `json:"signature"`
}

const (
	PreparationURI          = "/v1/store/message/preparation"
	SubmissionURI           = "/v1/store/message/submission"
	QueryMessageURI         = "/v1/store/message/query"
	GetBlockSummaryURI      = "/v1/store/block/summary"
	GetTransactionDetailURI = "/v1/store/transaction/detail"
	GetBlockListURI         = "/v1/store/block/list"
)

var (
	blockClient *client.TDCClient
)

func init() {
	config, err := utils.NewConfig(config.GetConfig().DACConfig.ConfigPath)
	blockClient, err = client.NewClient(config)
	if err != nil {
		logger.Error("Init TDCClient error: %v", err)
	}
}
func GetBlockSummary() (*BlockSummary, error) {

	code, buf, _, err := blockClient.HttpsClient.DoGetRequest(blockClient.Config.Service.Url+GetBlockSummaryURI, nil, nil)
	if err != nil {
		return nil, err
	}
	if code != utils.RequestSuccess {
		return nil, errors.New(string(buf))
	}
	blockSummary := new(BlockSummary)
	err = json.Unmarshal(buf, blockSummary)
	if err != nil {
		return nil, err
	}
	return blockSummary, nil
}
func GetTransaction(txId string) (*Transaction, error) {
	headers := map[string]string{
		"tx_id": txId,
	}
	finalUrl := blockClient.Config.Service.Url + GetTransactionDetailURI + "?"
	i := 0
	sum := len(headers)
	for k, v := range headers {
		finalUrl = util.CombineTwoString(finalUrl, k+"="+v)
		i++
		if i != sum {
			finalUrl = util.CombineTwoString(finalUrl, "&")
		}
	}

	code, buf, _, err := blockClient.HttpsClient.DoGetRequest(finalUrl, nil, nil)
	if err != nil {
		return nil, err
	}
	if code != utils.RequestSuccess {
		return nil, errors.New(string(buf))
	}

	transactionResponse := new(GetTransactionResponse)
	err = json.Unmarshal(buf, transactionResponse)
	if err != nil {
		return nil, err
	}

	transaction := &Transaction{
		BlockID: strconv.FormatInt(int64(transactionResponse.BlockID), 10),
		TxId:    txId,
		Time:    transactionResponse.CreateTime,
	}
	return transaction, nil
}
func GetBlockList(start, end int64) (*BlockList, error) {
	url := blockClient.Config.Service.Url + GetBlockListURI + "?block_start=" + strconv.FormatInt(start, 10) + "&block_end=" + strconv.FormatInt(end, 10)
	code, buf, _, err := blockClient.HttpsClient.DoGetRequest(url, nil, nil)

	if err != nil {
		return nil, err
	}
	if code != utils.RequestSuccess {
		return nil, errors.New(string(buf))
	}
	blockList := new(BlockList)
	err = json.Unmarshal(buf, blockList)
	if err != nil {
		return nil, err
	}
	return blockList, nil
}
